#include "FiniteDiff/Intergrid.h"

template <int Dim>
void Intergrid<Dim>::restrictResidual(const Tensor<Real, Dim> &fineData, Tensor<Real, Dim> &coarseData) const
{
  ddfor(coarseGrid, [&](Vec<int, Dim> idx) {
    Real r = 0.0;
    ddfor(Box<Dim>(0, 1), [&](Vec<int, Dim> delta) {
      r += fineData(idx * 2 + delta);
    }, false);
    coarseData(idx) = r / (1 << Dim);
  });
}

template <int Dim>
void Intergrid<Dim>::incrementalProlong(const Tensor<Real, Dim> &coarseData, Tensor<Real, Dim> &fineData) const
{
  // perform bilinear interpolation
//  ddfor(fineGrid, [&](const Vec<int, Dim> &idx) {
//    Vec<int, Dim> delta;
//    for(int d = 0; d < Dim; ++d)
//      delta[d] = (idx[d] % 2) ? (1) : (-1);
//    Real r = 0.0;
//    ddfor(Vec<int, Dim>(2), [&](const Vec<int, Dim> &jdx) {
//      r += coarseData(idx / 2 + jdx * delta) * std::pow(3.0, Dim - sum(jdx));
//    }, false);
//    fineData(idx) += r / std::pow(4.0, Dim);
//  });
  // patchwise constant interpolation
  ddfor(fineGrid, [&](const Vec<int, Dim> &idx) {
    fineData(idx) += coarseData(idx / 2);
  });
}

//============================================================
template class Intergrid<SpaceDim>;
